home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / Main.bin / BigDecimal.java < prev    next >
Text File  |  1998-11-04  |  25KB  |  662 lines

  1. /*
  2.  * @(#)BigDecimal.java    1.8 98/10/28
  3.  *
  4.  * Copyright 1996-1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  * 
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. package java.math;
  16.  
  17. /**
  18.  * Immutable, arbitrary-precision signed decimal numbers.  A BigDecimal
  19.  * consists of an arbitrary precision integer value and a non-negative
  20.  * integer scale, which represents the number of decimal digits to the
  21.  * right of the decimal point.  (The number represented by the BigDecimal
  22.  * is intVal/10**scale.)  BigDecimals provide operations for basic arithmetic,
  23.  * scale manipulation, comparison, format conversion and hashing.
  24.  *
  25.  * <p>The BigDecimal class gives its user complete control over rounding
  26.  * behavior, forcing the user to explicitly specify a rounding behavior for
  27.  * operations capable of discarding precision (divide and setScale).  Eight
  28.  * <em>rounding modes</em> are provided for this purpose.
  29.  *
  30.  * Two types of operations are provided for manipulating the scale of a
  31.  * BigDecimal: scaling/rounding operations and decimal point motion operations.
  32.  * Scaling/Rounding operations (SetScale) return a BigDecimal whose value is
  33.  * approximately (or exactly) equal to that of the operand, but whose scale is
  34.  * the specified value; that is, they increase or decrease the precision
  35.  * of the number with minimal effect on its value.  Decimal point motion
  36.  * operations (movePointLeft and movePointRight) return a BigDecimal created
  37.  * from the operand by moving the decimal point a specified distance in the
  38.  * specified direction; that is, they change a number's value without affecting
  39.  * its precision.
  40.  *
  41.  * @see BigInteger
  42.  * @version     1.8, 98/10/29
  43.  * @author      Josh Bloch
  44.  */
  45. public class BigDecimal extends Number {
  46.     private BigInteger intVal;
  47.     private int           scale = 0;
  48.  
  49.     /* Appease the serialization gods */
  50.     private static final long serialVersionUID = 6108874887143696463L;
  51.  
  52.     // Constructors
  53.  
  54.     /**
  55.      * Constructs a BigDecimal from a string containing an optional minus
  56.      * sign followed by a sequence of zero or more decimal digits, optionally
  57.      * followed by a fraction, which consists of a decimal point followed by
  58.      * zero or more decimal digits.  The string must contain at least one
  59.      * digit in the integer or fractional part.  The scale of the resulting
  60.      * BigDecimal will be the number of digits to the right of the decimal
  61.      * point in the string, or 0 if the string contains no decimal point.
  62.      * The character-to-digit mapping is provided by Character.digit.
  63.      * Any extraneous characters (including whitespace) will result in
  64.      * a NumberFormatException.
  65.      */
  66.     public BigDecimal(String val) throws NumberFormatException {
  67.     int pointPos = val.indexOf('.');
  68.     if (pointPos == -1) {             /* e.g. "123" */
  69.         intVal = new BigInteger(val);
  70.     } else if (pointPos == val.length()-1) { /* e.g. "123." */
  71.         intVal = new BigInteger(val.substring(0, val.length()-1));
  72.     } else {    /* Fraction part exists */
  73.         String fracString = val.substring(pointPos+1);
  74.         scale = fracString.length();
  75.         BigInteger fraction =  new BigInteger(fracString);
  76.         if (fraction.signum() < 0)         /* ".-123" illegal! */
  77.         throw new NumberFormatException();
  78.  
  79.         if (pointPos==0) {             /* e.g.  ".123" */
  80.         intVal = fraction;
  81.         } else if (val.charAt(0)=='-' && pointPos==1) {
  82.         intVal = fraction.negate();     /* e.g. "-.123" */
  83.         } else  {                 /* e.g. "-123.456" */
  84.         String intString = val.substring(0, pointPos);
  85.         BigInteger intPart = new BigInteger(intString);
  86.         if (val.charAt(0) == '-')
  87.             fraction = fraction.negate();
  88.         intVal = timesTenToThe(intPart, scale).add(fraction);
  89.         }
  90.     }
  91.     }
  92.  
  93.     /**
  94.      * Translates a double into a BigDecimal.  The scale of the BigDecimal
  95.      * is the smallest value such that (10**scale * val) is an integer.
  96.      * A double whose value is -infinity, +infinity or NaN will result in a
  97.      * NumberFormatException.
  98.      */
  99.     public BigDecimal(double val) throws NumberFormatException{
  100.     if (Double.isInfinite(val) || Double.isNaN(val))
  101.         throw new NumberFormatException("Infinite or NaN");
  102.  
  103.     /*
  104.      * Translate the double into sign, exponent and mantissa, according
  105.      * to the formulae in JLS, Section 20.10.22.
  106.      */
  107.     long valBits = Double.doubleToLongBits(val);
  108.     int sign = ((valBits >> 63)==0 ? 1 : -1);
  109.     int exponent = (int) ((valBits >> 52) & 0x7ffL);
  110.     long mantissa = (exponent==0 ? (valBits & ((1L<<52) - 1)) << 1
  111.                      : (valBits & ((1L<<52) - 1)) | (1L<<52));
  112.     exponent -= 1075;
  113.     /* At this point, val == sign * mantissa * 2**exponent */
  114.  
  115.     /*
  116.      * Special case zero to to supress nonterminating normalization
  117.      * and bogus scale calculation.
  118.      */
  119.     if (mantissa == 0) {
  120.         intVal = BigInteger.valueOf(0);
  121.         return;
  122.     }
  123.  
  124.     /* Normalize */
  125.     while((mantissa & 1) == 0) {    /*  i.e., Mantissa is even */
  126.         mantissa >>= 1;
  127.         exponent++;
  128.     }
  129.  
  130.     /* Calculate intVal and scale */
  131.     intVal = BigInteger.valueOf(sign*mantissa);
  132.     if (exponent < 0) {
  133.         intVal = intVal.multiply(BigInteger.valueOf(5).pow(-exponent));
  134.         scale = -exponent;
  135.     } else if (exponent > 0) {
  136.         intVal = intVal.multiply(BigInteger.valueOf(2).pow(exponent));
  137.     }
  138.     }
  139.  
  140.     /**
  141.      * Translates a BigInteger into a BigDecimal.  The scale of the BigDecimal
  142.      * is zero.
  143.      */
  144.     public BigDecimal(BigInteger val) {
  145.     intVal = val;
  146.     }
  147.  
  148.     /**
  149.      * Translates a BigInteger and a scale into a BigDecimal.  The value
  150.      * of the BigDecimal is (BigInteger/10**scale).  A negative scale
  151.      * will result in a NumberFormatException.
  152.      */
  153.     public BigDecimal(BigInteger val, int scale) throws NumberFormatException {
  154.     if (scale < 0)
  155.         throw new NumberFormatException("Negative scale");
  156.  
  157.     intVal = val;
  158.     this.scale = scale;
  159.     }
  160.  
  161.  
  162.     // Static Factory Methods
  163.  
  164.     /**
  165.      * Returns a BigDecimal with a value of (val/10**scale).  This factory
  166.      * is provided in preference to a (long) constructor because it allows
  167.      * for reuse of frequently used BigDecimals (like 0 and 1), obviating
  168.      * the need for exported constants.  A negative scale will result in a
  169.      * NumberFormatException.
  170.      */
  171.     public static BigDecimal valueOf(long val, int scale)
  172.         throws NumberFormatException {
  173.     return new BigDecimal(BigInteger.valueOf(val), scale);
  174.     }
  175.  
  176.     /**
  177.      * Returns a BigDecimal with the given value and a scale of zero.
  178.      * This factory is provided in preference to a (long) constructor
  179.      * because it allows for reuse of frequently used BigDecimals (like
  180.      * 0 and 1), obviating the need for exported constants.
  181.      */
  182.     public static BigDecimal valueOf(long val) {
  183.     return valueOf(val, 0);
  184.     }
  185.  
  186.  
  187.     // Arithmetic Operations
  188.  
  189.     /**
  190.      * Returns a BigDecimal whose value is (this + val), and whose scale is
  191.      * MAX(this.scale(), val.scale).
  192.      */
  193.     public BigDecimal add(BigDecimal val){
  194.     BigDecimal arg[] = new BigDecimal[2];
  195.     arg[0] = this;    arg[1] = val;
  196.     matchScale(arg);
  197.     return new BigDecimal(arg[0].intVal.add(arg[1].intVal), arg[0].scale);
  198.     }
  199.  
  200.     /**
  201.      * Returns a BigDecimal whose value is (this - val), and whose scale is
  202.      * MAX(this.scale(), val.scale).
  203.      */
  204.     public BigDecimal subtract(BigDecimal val){
  205.     BigDecimal arg[] = new BigDecimal[2];
  206.     arg[0] = this;    arg[1] = val;
  207.     matchScale(arg);
  208.     return new BigDecimal(arg[0].intVal.subtract(arg[1].intVal),
  209.                   arg[0].scale);
  210.     }
  211.  
  212.     /**
  213.      * Returns a BigDecimal whose value is (this * val), and whose scale is
  214.      * this.scale() + val.scale.
  215.      */
  216.     public BigDecimal multiply(BigDecimal val){
  217.     return new BigDecimal(intVal.multiply(val.intVal), scale+val.scale);
  218.     }
  219.  
  220.     /**
  221.      * Returns a BigDecimal whose value is (this / val), and whose scale
  222.      * is as specified.  If rounding must be performed to generate a
  223.      * result with the given scale, the specified rounding mode is
  224.      * applied.  Throws an ArithmeticException if val == 0, scale < 0,
  225.      * or the rounding mode is ROUND_UNNECESSARY and the specified scale
  226.      * is insufficient to represent the result of the division exactly.
  227.      * Throws an IllegalArgumentException if roundingMode does not
  228.      * represent a valid rounding mode.
  229.      */
  230.     public BigDecimal divide(BigDecimal val, int scale, int roundingMode)
  231.         throws ArithmeticException, IllegalArgumentException {
  232.     if (scale < 0)
  233.         throw new ArithmeticException("Negative scale");
  234.     if (roundingMode < ROUND_UP || roundingMode > ROUND_UNNECESSARY)
  235.         throw new IllegalArgumentException("Invalid rounding mode");
  236.  
  237.     /*
  238.      * Rescale dividend or divisor (whichever can be "upscaled" to
  239.      * produce correctly scaled quotient).
  240.      */
  241.     BigDecimal dividend, divisor;
  242.     if (scale + val.scale >= this.scale) {
  243.         dividend = this.setScale(scale + val.scale);
  244.         divisor = val;
  245.     } else {
  246.         dividend = this;
  247.         divisor = val.setScale(this.scale - scale);
  248.     }
  249.  
  250.     /* Do the division and return result if it's exact */
  251.     BigInteger i[] = dividend.intVal.divideAndRemainder(divisor.intVal);
  252.     BigInteger q = i[0], r = i[1];
  253.     if (r.signum() == 0)
  254.         return new BigDecimal(q, scale);
  255.     else if (roundingMode == ROUND_UNNECESSARY) /* Rounding prohibited */
  256.         throw new ArithmeticException("Rounding necessary");
  257.  
  258.     /* Round as appropriate */
  259.     int signum = dividend.signum() * divisor.signum(); /* Sign of result */
  260.     boolean increment;
  261.     if (roundingMode == ROUND_UP) {            /* Away from zero */
  262.         increment = true;
  263.     } else if (roundingMode == ROUND_DOWN) {    /* Towards zero */
  264.         increment = false;
  265.     } else if (roundingMode == ROUND_CEILING) { /* Towards +infinity */
  266.         increment = (signum > 0);
  267.     } else if (roundingMode == ROUND_FLOOR) {   /* Towards -infinity */
  268.         increment = (signum < 0);
  269.     } else { /* Remaining modes based on nearest-neighbor determination */
  270.         int cmpFracHalf = r.abs().multiply(BigInteger.valueOf(2)).
  271.                      compareTo(divisor.intVal.abs());
  272.         if (cmpFracHalf < 0) {       /* We're closer to higher digit */
  273.         increment = false;
  274.         } else if (cmpFracHalf > 0) {  /* We're closer to lower digit */
  275.         increment = true;
  276.         } else {                /* We're dead-center */
  277.         if (roundingMode == ROUND_HALF_UP)
  278.             increment = true;
  279.         else if (roundingMode == ROUND_HALF_DOWN)
  280.             increment = false;
  281.         else  /* roundingMode == ROUND_HALF_EVEN */
  282.             increment = q.testBit(0);    /* true iff q is odd */
  283.         }
  284.     }
  285.     return (increment
  286.         ? new BigDecimal(q.add(BigInteger.valueOf(signum)), scale)
  287.         : new BigDecimal(q, scale));
  288.     }
  289.  
  290.     /**
  291.      * Returns a BigDecimal whose value is (this / val), and whose scale
  292.      * is this.scale().  If rounding must be performed to generate a
  293.      * result with the given scale, the specified rounding mode is
  294.      * applied.  Throws an ArithmeticException if val == 0.  Throws
  295.      * an IllegalArgumentException if roundingMode does not represent a
  296.      * valid rounding mode.
  297.      */
  298.     public BigDecimal divide(BigDecimal val, int roundingMode)
  299.     throws ArithmeticException, IllegalArgumentException{
  300.         return this.divide(val, scale, roundingMode);
  301.     }
  302.  
  303.    /**
  304.     * Returns a BigDecimal whose value is the absolute value of this
  305.     * number, and whose scale is this.scale().
  306.     */
  307.     public BigDecimal abs(){
  308.     return (signum() < 0 ? negate() : this);
  309.     }
  310.  
  311.     /**
  312.      * Returns a BigDecimal whose value is -1 * this, and whose scale is
  313.      * this.scale().
  314.      */
  315.     public BigDecimal negate(){
  316.     return new BigDecimal(intVal.negate(), scale);
  317.     }
  318.  
  319.     /**
  320.      * Returns the signum function of this number (i.e., -1, 0 or 1 as
  321.      * the value of this number is negative, zero or positive).
  322.      */
  323.     public int signum(){
  324.     return intVal.signum();
  325.     }
  326.  
  327.     /**
  328.      * Returns the scale of this number.
  329.      */
  330.     public int scale(){
  331.     return scale;
  332.     }
  333.  
  334.  
  335.     // Rounding Modes
  336.  
  337.     /**
  338.      * Always increment the digit prior to a non-zero discarded fraction.
  339.      * Note that this rounding mode never decreases the magnitude.
  340.      * (Rounds away from zero.)
  341.      */
  342.     public final static int ROUND_UP =          0;
  343.  
  344.     /**
  345.      * Never increment the digit prior to a discarded fraction (i.e.,
  346.      * truncate).  Note that this rounding mode never increases the magnitude.
  347.      * (Rounds towards zero.)
  348.      */
  349.     public final static int ROUND_DOWN =      1;
  350.  
  351.     /**
  352.      * If the BigDecimal is positive, behave as for ROUND_UP; if negative,
  353.      * behave as for ROUND_DOWN.  Note that this rounding mode never decreases
  354.      * the value.  (Rounds towards positive infinity.)
  355.      */
  356.     public final static int ROUND_CEILING =      2;
  357.  
  358.     /**
  359.      * If the BigDecimal is positive, behave as for ROUND_DOWN; if negative
  360.      * behave as for ROUND_UP.  Note that this rounding mode never increases
  361.      * the value.  (Rounds towards negative infinity.)
  362.      */
  363.     public final static int ROUND_FLOOR =      3;
  364.  
  365.     /**
  366.      * Behave as for ROUND_UP if the discarded fraction is >= .5; otherwise,
  367.      * behave as for ROUND_DOWN.  (Rounds towards "nearest neighbor" unless
  368.      * both neighbors are equidistant, in which case rounds up.)
  369.      */
  370.     public final static int ROUND_HALF_UP =      4;
  371.  
  372.     /**
  373.      * Behave as for ROUND_UP if the discarded fraction is > .5; otherwise,
  374.      * behave as for ROUND_DOWN.   (Rounds towards "nearest neighbor" unless
  375.      * both neighbors are equidistant, in which case rounds down.)
  376.      */
  377.     public final static int ROUND_HALF_DOWN =      5;
  378.  
  379.     /**
  380.      * Behave as for ROUND_HALF_UP if the digit to the left of the discarded
  381.      * fraction is odd; behave as for ROUND_HALF_DOWN if it's even.  (Rounds
  382.      * towards the "nearest neighbor" unless both neighbors are equidistant,
  383.      * in which case, rounds towards the even neighbor.)
  384.      */
  385.     public final static int ROUND_HALF_EVEN =      6;
  386.  
  387.     /**
  388.      * This "pseudo-rounding-mode" is actually an assertion that the requested
  389.      * operation has an exact result, hence no rounding is necessary.  If this
  390.      * rounding mode is specified on an operation that yields an inexact result,
  391.      * an arithmetic exception is thrown.
  392.      */
  393.     public final static int ROUND_UNNECESSARY =  7;
  394.  
  395.  
  396.     // Scaling/Rounding Operations
  397.  
  398.     /**
  399.      * Returns a BigDecimal whose scale is the specified value, and whose
  400.      * integer value is determined by multiplying or dividing this BigDecimal's
  401.      * integer value by the appropriate power of ten to maintain the overall
  402.      * value.  If the scale is reduced by the operation, the integer value
  403.      * must be divided (rather than multiplied), and precision may be lost;
  404.      * in this case, the specified rounding mode is applied to the division.
  405.      * Throws an ArithmeticException if scale is negative, or the rounding
  406.      * mode is ROUND_UNNECESSARY and it is impossible to perform the
  407.      * specified scaling operation without loss of precision.  Throws an
  408.      * IllegalArgumentException if roundingMode does not represent a valid
  409.      * rounding mode.
  410.      */
  411.     public BigDecimal setScale(int scale, int roundingMode)
  412.     throws ArithmeticException, IllegalArgumentException {
  413.     if (scale < 0)
  414.         throw new ArithmeticException("Negative scale");
  415.     if (roundingMode < ROUND_UP || roundingMode > ROUND_UNNECESSARY)
  416.         throw new IllegalArgumentException("Invalid rounding mode");
  417.  
  418.     /* Handle the easy cases */
  419.     if (scale == this.scale)
  420.         return this;
  421.     else if (scale > this.scale)
  422.         return new BigDecimal(timesTenToThe(intVal, scale-this.scale),
  423.                   scale);
  424.     else /* scale < this.scale */
  425.         return divide(valueOf(1), scale, roundingMode);
  426.     }
  427.  
  428.     /**
  429.      * Returns a BigDecimal whose scale is the specified value, and whose
  430.      * value is exactly equal to this number's.  Throws an ArithmeticException
  431.      * if this is not possible.  This call is typically used to increase
  432.      * the scale, in which case it is guaranteed that there exists a BigDecimal
  433.      * of the specified scale and the correct value.  The call can also be used
  434.      * to reduce the scale if the caller knows that the number has sufficiently
  435.      * many zeros at the end of its fractional part (i.e., factors of ten in
  436.      * its integer value) to allow for the rescaling without loss of precision.
  437.      * Note that this call returns the same result as the two argument version
  438.      * of setScale, but saves the caller the trouble of specifying a rounding
  439.      * mode in cases where it is irrelevant.
  440.      */
  441.     public BigDecimal setScale(int scale)
  442.     throws ArithmeticException, IllegalArgumentException
  443.     {
  444.     return setScale(scale, ROUND_UNNECESSARY);
  445.     }
  446.  
  447.  
  448.     // Decimal Point Motion Operations
  449.  
  450.     /**
  451.      * Returns a BigDecimal which is equivalent to this one with the decimal
  452.      * point moved n places to the left.  If n is non-negative, the call merely
  453.      * adds n to the scale.  If n is negative, the call is equivalent to
  454.      * movePointRight(-n).  (The BigDecimal returned by this call has value
  455.      * (this * 10**-n) and scale MAX(this.scale()+n, 0).)
  456.      */
  457.     public BigDecimal movePointLeft(int n){
  458.     return (n>=0 ? new BigDecimal(intVal, scale+n) : movePointRight(-n));
  459.     }
  460.  
  461.     /**
  462.      * Moves the decimal point the specified number of places to the right.
  463.      * If this number's scale is >= n, the call merely subtracts n from the
  464.      * scale; otherwise, it sets the scale to zero, and multiplies the integer
  465.      * value by 10 ** (n - this.scale).  If n is negative, the call is
  466.      * equivalent to movePointLeft(-n). (The BigDecimal returned by this call
  467.      * has value (this * 10**n) and scale MAX(this.scale()-n, 0).)
  468.      */
  469.     public BigDecimal movePointRight(int n){
  470.     return (scale >= n ? new BigDecimal(intVal, scale-n)
  471.                    : new BigDecimal(timesTenToThe(intVal, n-scale),0));
  472.     }
  473.  
  474.     // Comparison Operations
  475.  
  476.     /**
  477.      * Returns -1, 0 or 1 as this number is less than, equal to, or greater
  478.      * than val.  Two BigDecimals that are equal in value but have a
  479.      * different scale (e.g., 2.0, 2.00) are considered equal by this method.
  480.      * This method is provided in preference to individual methods for each
  481.      * of the six boolean comparison operators (<, ==, >, >=, !=, <=).  The
  482.      * suggested idiom for performing these comparisons is:  (x.compareTo(y)
  483.      * <op> 0), where <op> is one of the six comparison operators.
  484.      */
  485.     public int compareTo(BigDecimal val){
  486.     /* Optimization: would run fine without the next three lines */
  487.     int sigDiff = signum() - val.signum();
  488.     if (sigDiff != 0)
  489.         return (sigDiff > 0 ? 1 : -1);
  490.  
  491.     /* If signs match, scale and compare intVals */
  492.     BigDecimal arg[] = new BigDecimal[2];
  493.     arg[0] = this;    arg[1] = val;
  494.     matchScale(arg);
  495.     return arg[0].intVal.compareTo(arg[1].intVal);
  496.     }
  497.  
  498.     /**
  499.      * Returns true iff x is a BigDecimal whose value is equal to this number.
  500.      * This method is provided so that BigDecimals can be used as hash keys.
  501.      * Unlike compareTo, this method considers two BigDecimals equal only
  502.      * if they are equal in value and scale.
  503.      */
  504.     public boolean equals(Object x){
  505.     if (!(x instanceof BigDecimal))
  506.         return false;
  507.     BigDecimal xDec = (BigDecimal) x;
  508.  
  509.     return scale == xDec.scale && intVal.equals(xDec.intVal);
  510.     }
  511.  
  512.     /**
  513.      * Returns the BigDecimal whose value is the lesser of this and val.
  514.      * If the values are equal (as defined by the compareTo operator),
  515.      * either may be returned.
  516.      */
  517.     public BigDecimal min(BigDecimal val){
  518.     return (compareTo(val)<0 ? this : val);
  519.     }
  520.  
  521.     /**
  522.      * Returns the BigDecimal whose value is the greater of this and val.
  523.      * If the values are equal (as defined by the compareTo operator),
  524.      * either may be returned.
  525.      */
  526.     public BigDecimal max(BigDecimal val){
  527.     return (compareTo(val)>0 ? this : val);
  528.     }
  529.  
  530.  
  531.     // Hash Function
  532.  
  533.     /**
  534.      * Computes a hash code for this object.  Note that two BigDecimals
  535.      * that are numerically equal but differ in scale (e.g., 2.0, 2.00) will
  536.      * not generally have the same hash code.
  537.      */
  538.     public int hashCode(){
  539.     return 37*intVal.hashCode() + scale;
  540.     }
  541.  
  542.     // Format Converters
  543.  
  544.     /**
  545.      * Returns the string representation of this number.  The digit-to-
  546.      * character mapping provided by Character.forDigit is used.  The minus
  547.      * sign and decimal point are used to indicate sign and scale.  (This
  548.      * representation is compatible with the (String, int) constructor.)
  549.      */
  550.     public String toString(){
  551.     if (scale == 0)    /* No decimal point */
  552.         return intVal.toString();
  553.  
  554.     /* Insert decimal point */
  555.     StringBuffer buf;
  556.     String intString = intVal.abs().toString();
  557.     int signum = signum();
  558.     int insertionPoint = intString.length() - scale;
  559.     if (insertionPoint == 0) {  /* Point goes right before intVal */
  560.         return (signum<0 ? "-0." : "0.") + intString;
  561.     } else if (insertionPoint > 0) { /* Point goes inside intVal */
  562.         buf = new StringBuffer(intString);
  563.         buf.insert(insertionPoint, '.');
  564.         if (signum < 0)
  565.         buf.insert(0, '-');
  566.     } else { /* We must insert zeros between point and intVal */
  567.         buf = new StringBuffer(3-insertionPoint + intString.length());
  568.         buf.append(signum<0 ? "-0." : "0.");
  569.         for (int i=0; i<-insertionPoint; i++)
  570.         buf.append('0');
  571.         buf.append(intString);
  572.     }
  573.     return buf.toString();
  574.     }
  575.  
  576.     /**
  577.      * Converts this number to a BigInteger.  Standard narrowing primitive
  578.      * conversion as per The Java Language Specification.  In particular,
  579.      * note that any fractional part of this number will be truncated.
  580.      */
  581.     public BigInteger toBigInteger(){
  582.     return (scale==0 ? intVal
  583.              : intVal.divide(BigInteger.valueOf(10).pow(scale)));
  584.     }
  585.  
  586.     /**
  587.      * Converts this number to an int.  Standard narrowing primitive conversion
  588.      * as per The Java Language Specification.  In particular, note that any
  589.      * fractional part of this number will be truncated.
  590.      */
  591.     public int intValue(){
  592.     return toBigInteger().intValue();
  593.     }
  594.  
  595.     /**
  596.      * Converts this number to a long.  Standard narrowing primitive conversion
  597.      * as per The Java Language Specification.  In particular, note that any
  598.      * fractional part of this number will be truncated.
  599.      */
  600.     public long longValue(){
  601.     return toBigInteger().longValue();
  602.     }
  603.  
  604.     /**
  605.      * Converts this number to a float.  Similar to the double-to-float
  606.      * narrowing primitive conversion defined in The Java Language
  607.      * Specification: if the number has too great a magnitude to represent
  608.      * as a float, it will be converted to infinity or negative infinity,
  609.      * as appropriate.
  610.      */
  611.     public float floatValue(){
  612.     /* Somewhat inefficient, but guaranteed to work. */
  613.     return Float.valueOf(this.toString()).floatValue();
  614.     }
  615.  
  616.     /**
  617.      * Converts the number to a double.  Similar to the double-to-float
  618.      * narrowing primitive conversion defined in The Java Language
  619.      * Specification: if the number has too great a magnitude to represent
  620.      * as a double, it will be converted to infinity or negative infinity,
  621.      * as appropriate.
  622.      */
  623.     public double doubleValue(){
  624.     /* Somewhat inefficient, but guaranteed to work. */
  625.     return Double.valueOf(this.toString()).doubleValue();
  626.     }
  627.  
  628.  
  629.     // Private "Helper" Methods
  630.  
  631.     /* Returns (a * 10^b) */
  632.     private static BigInteger timesTenToThe(BigInteger a, int b) {
  633.     return a.multiply(BigInteger.valueOf(10).pow(b));
  634.     }
  635.  
  636.     /*
  637.      * If the scales of val[0] and val[1] differ, rescale (non-destructively)
  638.      * the lower-scaled BigDecimal so they match.
  639.      */
  640.     private static void matchScale(BigDecimal[] val) {
  641.     if (val[0].scale < val[1].scale)
  642.         val[0] = val[0].setScale(val[1].scale);
  643.     else if (val[1].scale < val[0].scale)
  644.         val[1] = val[1].setScale(val[0].scale);
  645.     }
  646.  
  647.     /**
  648.      * Reconstitute the <tt>BigDecimal</tt> instance from a stream (that is,
  649.      * deserialize it).
  650.      */
  651.     private synchronized void readObject(java.io.ObjectInputStream s)
  652.         throws java.io.IOException, ClassNotFoundException {
  653.         // Read in all fields
  654.     s.defaultReadObject();
  655.  
  656.         // Validate scale factor
  657.         if (scale < 0)
  658.         throw new java.io.StreamCorruptedException(
  659.                                       "BigDecimal: Negative scale");
  660.     }
  661. }
  662.